﻿#include "WavLibrary.h"
#include "../../Settings.h"
#include "../SoundManager.h"

using namespace SlimDX::DirectSound;
using namespace SlimDX::Multimedia;

namespace Client::MirSounds
{

    int WavLibrary::getIndex() const
    {
        return Index;
    }

    void WavLibrary::setIndex(int value)
    {
        Index = value;
    }

    WavLibrary *WavLibrary::TryCreate(int index, const std::string &fileName, bool loop)
    {
        fileName = FileSystem::combine(Settings::SoundPath, Path::GetFileNameWithoutExtension(fileName) + ".wav");

        if (FileSystem::fileExists(fileName))
        {
            return new WavLibrary(index, fileName, loop);
        }

        return nullptr;
    }

    WavLibrary::WavLibrary(int index, const std::string &fileName, bool loop) : _data(std::vector<unsigned char>(_desc->SizeInBytes))
    {
        setIndex(index);

        _stream = new WaveStream(fileName);

        _desc = new SoundBufferDescription();
        _desc->SizeInBytes = static_cast<int>(_stream->Length);
        _desc->Flags = BufferFlags::ControlVolume | BufferFlags::ControlPan | BufferFlags::GlobalFocus;
        _desc->Format = _stream->Format;

        _stream->Read(_data, 0, static_cast<int>(_stream->Length));

        _loop = loop;

        _bufferList = std::vector<SecondarySoundBuffer*>();

        Play();
    }

    void WavLibrary::Play()
    {
        if (_stream == nullptr)
        {
            return;
        }

        if (_loop)
        {
            if (_bufferList.empty())
            {
                SecondarySoundBuffer *buffer = new SecondarySoundBuffer(SoundManager::Device, _desc);
                buffer->Volume = SoundManager::getVol();
                buffer->Write(_data, 0, LockFlags::None);
                _bufferList.push_back(buffer);

//C# TO C++ CONVERTER TODO TASK: A 'delete buffer' statement was not added since buffer was passed to a method or constructor. Handle memory management manually.
            }
            else if (_bufferList[0] == nullptr || _bufferList[0]->Disposed)
            {
                SecondarySoundBuffer *buffer = new SecondarySoundBuffer(SoundManager::Device, _desc);
                buffer->Volume = SoundManager::getVol();
                buffer->Write(_data, 0, LockFlags::None);
                _bufferList[0] = buffer;

                delete buffer;
            }

            if (_bufferList[0]->Status != BufferStatus::Playing)
            {
                _bufferList[0]->Play(0, PlayFlags::Looping);
            }
        }
        else
        {
            for (int i = _bufferList.size() - 1; i >= 0; i--)
            {
                if (_bufferList[i] == nullptr || _bufferList[i]->Disposed)
                {
                    _bufferList.erase(_bufferList.begin() + i);
                    continue;
                }

                if (_bufferList[i]->Status != BufferStatus::Playing)
                {
                    _bufferList[i]->Volume = SoundManager::getVol();
                    _bufferList[i]->Play(0, 0);
                    return;
                }
            }

            if (_bufferList.size() >= Settings::SoundOverLap)
            {
                return;
            }

            SecondarySoundBuffer *buffer = new SecondarySoundBuffer(SoundManager::Device, _desc);
            buffer->Volume = SoundManager::getVol();
            buffer->Pan = 0;
            buffer->Write(_data, 0, LockFlags::None);
            buffer->Play(0, 0);
            _bufferList.push_back(buffer);

//C# TO C++ CONVERTER TODO TASK: A 'delete buffer' statement was not added since buffer was passed to a method or constructor. Handle memory management manually.
        }
    }

    void WavLibrary::Stop()
    {
        if (_bufferList.empty() || _bufferList.empty())
        {
            return;
        }

        if (_loop)
        {
            _bufferList[0]->Dispose();
        }
        else
        {
            for (int i = 0; i < _bufferList.size(); i++)
            {
                _bufferList[i]->Dispose();
            }
            _bufferList.clear();
        }
    }

    void WavLibrary::Dispose()
    {
        delete _desc;
        if (_stream != nullptr)
        {
            _stream->Dispose();
        }
        _stream = nullptr;

        if (!_bufferList.empty())
        {
        for (int i = 0; i < _bufferList.size(); i++)
        {
            _bufferList[i]->Dispose();
        }
        }
        _bufferList = std::vector<SecondarySoundBuffer*>();

        _loop = false;
    }

    void WavLibrary::SetVolume(int vol)
    {
        if (_bufferList.empty())
        {
            return;
        }
        if (vol <= -3000)
        {
            vol = -10000;
        }

        for (int i = 0; i < _bufferList.size(); i++)
        {
            if (_bufferList[i] != nullptr && !_bufferList[i]->Disposed)
            {
                _bufferList[i]->Volume = vol;
            }
        }
    }
}
